/*
 * test_tp2855.c
 *
 *  Created on: 2024年3月12日
 *      Author: NI
 */

#include "tp2855_reg.h"
#include "capture-decoder.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "imx8-capture.h"
#include "imx8-sig.h"
#include "imx8-windows.h"
#include <dlfcn.h>
#include <stdlib.h>
//#include <stddef.h>

camera_decoder_t * decoder = NULL;
//static capture_device_t soc;
capture_api_t api;
void * ctx;

#define LOG_ERROR 	printf

screen_context_t screen_ctx;
screen_windows_dev_t windows_dev;

int initWindowsDev(screen_windows_dev_t * a){
	a->screen_ctx = &screen_ctx;
	a->display = 2;
//	a->index = 1;
//	a->pos[1] = a->pos[0] = 0;
	a->size[1] = a->size[0] = 800;
//	a->size[0] = 500;a->size[1] = 500;
	a->pipeline = -1;
	a->format = SCREEN_FORMAT_YUY2;
	a->flip = 0;
	a->mirror = 0;
	a->rotation = 0;
	a->buffer_size[0] = 1280;a->buffer_size[1] = 720;
	a->zorder = 0;
	a->transparency = SCREEN_TRANSPARENCY_NONE;
	strcpy(a->id_string, "win-1");
	a->visit = 1;
	a->num_buffers = 5;


	return 0;
}

int main(int argc, char ** argv){
	int ret = -1;
	ret = init_sig();
	if(ret){
		printf("init sig fail\n");
		return -1;
	}

	ret = camera_decoder_init(&decoder);
	if(ret != 0){
		printf("camera_decoder_init fail\n");
		return -1;
	}
	//strcpy(decoder->i2c_path, "/dev/i2c1");

	decoder->camera_use = 4;

	ret = camera_decoder_set_property(decoder, DECODER_I2C_PATH, (void *)"/dev/i2c9");
	if(ret != 0){
		printf("DECODER_I2C_PATH set fail\n");
		goto fail;
	}

	decoder->decoder_addr = 0x44;
	decoder->mipi_config = MIPI_4CH4LANE_594M;

	int i = 0;
	for(i = 0; i < CH_ALL; i++){
		decoder->fmt[i] = HD30;
		decoder->std[i] = STD_HDA;
	}

	printf("=============decoder config=============\n");
	printf("camera_use:%d\n", decoder->camera_use);
	printf("i2c_path:%s\n", decoder->i2c_path);
	printf("i2c_fd:%d", decoder->i2c_fd);
	printf("fmt:%d\n", decoder->fmt[0]);
	printf("std:%d\n", decoder->std[0]);
	printf("========================================\n");

	printf("decoder init reg map\n");

	uint8_t channel[1];
	channel[0] = (uint8_t)CH_ALL;
	ret = camera_decoder_set_property(decoder, DECODER_INIT_REG_MAP, (void *)channel);
	if(ret != 0){
		printf("DECODER_INIT_REG_MAP fail\n");
		goto fail;
	}

	printf("decoder dump register\n\n");
	sleep(1);


//	printf("decoder->i2c_fd = %d\n",decoder->i2c_fd);

//	uint8_t value = 0;
//	for(i = 0; i < CH_ALL; i++){
//		ret = camera_decoder_read_reg(i, 0x40, &value);
//		if(ret != 0){
//			printf("camera_decoder_read_reg fail\n");
//			goto fail;
//		}
//		printf("value ");
//	}
//	printf("\n");

	ret = camera_decoder_set_property(decoder, DECODER_DUMP_REGISTER, NULL);
	if(ret != 0){
		printf("DECODER_I2C_PATH set fail\n");
		goto fail;
	}
//===============================================================================================================

	ret = screen_create_context(&screen_ctx, 0);
	if (ret)
	{
		LOG_ERROR("screen_context_create");
		goto fail;
	}

	initWindowsDev(&windows_dev);
	if(argc > 1){
		windows_dev.index = atoi(argv[1]);
		printf("Index: %d\n", windows_dev.index);
		int tmp = windows_dev.index;
		if(tmp){
			windows_dev.pos[0] = 500;
			tmp --;
		}
		if(tmp){
			windows_dev.pos[0] = 0;
			windows_dev.pos[1] = 500;
			tmp --;
		}
		if(tmp){
			windows_dev.pos[0] = windows_dev.pos[1] = 500;
		}
	}else{
		windows_dev.index = 0;
	}


	ret = screen_create_window(&windows_dev.screen_win, screen_ctx);
	if (ret)
	{
		LOG_ERROR("screen_create_window");
		goto fail1;
	}

	ret = initWin(&windows_dev, windows_dev.index);
	if (ret)
	{
		printf("initWin fail\n");
		goto fail2;
	}

//===============================================================================================================
#define IMX_ISI_SRC_MIPI_CSI_0	2
#define IMX_ISI_SRC_MIPI_CSI_1	3
#define IMX_ISI_SRC_CI_PI		4

//	typedef struct
//	{
//		screen_buffer_t *screen_buf;
//		void **pointers;
//		uint64_t *frame_timestamp;
//		uint32_t *frame_flags;
//		uint32_t *frame_nbytes;
//		uint32_t *frame_seqno;
//	} buff_info;

//	buff_info saveBuff[4];
	char * norm = CAPTURE_NORM_NTSC_M_J;

//	int index = 0;
//	int stride;
//	int size[2] = {1280, 720};
	ret = capture_get_device_api1("libcapture-soc-imx8x.so", 0, &api);
	if(ret){
		printf("capture_get_device_api\n");
		goto fail2;
	}
//	ctx = calloc(1, sizeof(capture_context_t));
//	if(ctx == NULL){
//		printf("Calloc ctx fail\n");
//	}
	ctx = api.capture_create_context(0);
	if(!ctx){
		printf("capture_create_context\n");
		goto fail3;
	}

retry:
#define	IMX_DEV_ISI 0
	if(api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DEVICE, IMX_DEV_ISI)){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}

	int source = 2;
	if(api.capture_set_property_i(ctx, CAPTURE_PROPERTY_SRC_INDEX, source)){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}

	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_INTERFACE_TYPE, CAPTURE_IF_MIPI_CSI2);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_CSI2_NUM_DATA_LANES, 4);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}

	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_CSI2_VCHANNEL_NUM, windows_dev.index);//todo
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DEINTERLACE_MODE, CAPTURE_DEINTERLACE_NONE_MODE);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DEINTERLACE_FLAGS, 0);//CAPTURE_DEI_WEAVE_FLAG_BOTTOM_TOP
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}

	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_FRAME_NBUFFERS, windows_dev.render_buffer_count);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_p(ctx, CAPTURE_PROPERTY_FRAME_BUFFERS, windows_dev.pointers);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_SRC_FORMAT, SCREEN_FORMAT_YUY2);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	printf("windows_dev.stride is %d\n", windows_dev.stride);
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DST_STRIDE, windows_dev.stride);//一行的字节数
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DST_FORMAT, windows_dev.format);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}

	printf("==========size: %d - %d\n",  windows_dev.size[0],  windows_dev.size[1]);

	printf("==========buffer_size: %d - %d\n",  windows_dev.buffer_size[0],  windows_dev.buffer_size[1]);
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_SRC_WIDTH, windows_dev.buffer_size[0]);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_SRC_HEIGHT, windows_dev.buffer_size[1]);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_CROP_WIDTH, windows_dev.buffer_size[0]);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_CROP_HEIGHT, windows_dev.buffer_size[1]);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DST_WIDTH, windows_dev.buffer_size[0]);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_DST_HEIGHT, windows_dev.buffer_size[1]);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
#if 1
	if(api.capture_is_property(ctx, CAPTURE_PROPERTY_NORM)){
		ret = api.capture_set_property_p(ctx, CAPTURE_PROPERTY_NORM, norm);
		if(ret){
			printf("[%s]:%d\n", __func__, __LINE__);
			goto fail4;
		}
		printf("Set CAPTURE_PROPERTY_NORM\n");
	}else{
		printf("Do not support CAPTURE_PROPERTY_NORM\n");
	}

	enum imx_xrdc_enable {
		IMX_XRDC_DISABLED,
		IMX_XRDC_ENABLED,
		IMX_XRDC_DEFAULT,
	};
#define CAPTURE_PROPERTY_IMX8X_XRDC_ENABLE		CAPTURE_PROPERTY('I','X','X','E')
	if(api.capture_is_property(ctx, CAPTURE_PROPERTY_IMX8X_XRDC_ENABLE)){
		ret = api.capture_set_property_i(ctx, CAPTURE_PROPERTY_IMX8X_XRDC_ENABLE, IMX_XRDC_DISABLED);
		if(ret){
			printf("[%s]:%d\n", __func__, __LINE__);
			goto fail4;
		}
		printf("Set CAPTURE_PROPERTY_IMX8X_XRDC_ENABLE\n");
	}else{
		printf("Do not support CAPTURE_PROPERTY_IMX8X_XRDC_ENABLE\n");
	}
#endif

	ret = api.capture_set_property_i(ctx, CAPTURE_ENABLE, 1);
	if(ret){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}


	ret = api.capture_update(ctx, 0);
	if(ret == -1){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail4;
	}
	printf("ALL init finish\n");
#define POST_CAMERA
#ifdef POST_CAMERA

//#define CAMERA_BUG1
#ifdef	CAMERA_BUG1
	void * ctx_test;
	ctx_test = api.capture_create_context(0);
	if(!ctx_test){
		printf("capture_create_context ctx_test\n");
		goto fail4;
	}
	if(api.capture_set_property_i(ctx_test, CAPTURE_PROPERTY_DEVICE, IMX_DEV_ISI)){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail5;
	}
	if(api.capture_set_property_i(ctx_test, CAPTURE_PROPERTY_SRC_INDEX, source)){
		printf("[%s]:%d\n", __func__, __LINE__);
		goto fail5;
	}
//	ret = api.capture_update(ctx_test, 0);
//	if(ret == -1){
//		printf("[%s]:%d\n", __func__, __LINE__);
//		goto fail5;
//	}
	api.capture_destroy_context(ctx_test);
#endif

	long long timeout = 3000000000;
	int rect[4] = {0,0,1280,720};
	while(!aborted){
		int buf_idx = api.capture_get_frame(ctx, (uint64_t)(timeout), CAPTURE_FLAG_LATEST_FRAME);
		if(buf_idx == -1){
			printf("capture_get_frame fail\n");

			goto retry;
			continue;
		}
		screen_post_window(windows_dev.screen_win, windows_dev.render_buffers[buf_idx], 1, rect, 0);
		api.capture_release_frame(ctx, buf_idx);
		delay(50);
	}

#endif



#ifdef CAMERA_BUG1
fail5:
	api.capture_destroy_context(ctx_test);
#endif
fail4:
	api.capture_destroy_context(ctx);

fail3:
	if (windows_dev.render_buffers != NULL)
	{
		free(windows_dev.render_buffers);
		free(windows_dev.pointers);
	}
	dlclose(handle);
fail2:
	screen_destroy_window(windows_dev.screen_win);
fail1:
	screen_destroy_context(screen_ctx);
fail:
	camera_decoder_deinit(decoder);

	return 0;
}
